package com.shop.front.service.sms;

import com.shop.front.property.BusinessProps;
import com.shop.front.response.FrontRetEnum;
import com.shop.common.partner.sms.ISMS;
import com.shop.domain.sms.SmsCode;
import com.shop.front.consts.FrontConst;
import com.shop.front.dao.sms.SmsCodeDao;
import com.shop.util.DateUtil;
import com.shop.web.cache.RedisCache;
import com.shop.web.context.WebContext;
import com.shop.web.response.BaseResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Map;

@Service
@Slf4j
@Transactional
public class SmsService {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private BusinessProps businessProps;

    @Autowired
    private ISMS sms;

    @Autowired
    private SmsCodeDao smsCodeDao;

    public BaseResponse sendMessage(String mobile, String content, Map<String, String> args) {
        return new BaseResponse();
    }

    public BaseResponse sendCode(String cacheKey, String mobile, String code) {
        // 校验用户是否超过发送验证码次数
        int sendCount = smsCodeDao.countByMobileAndDate(mobile, DateUtil.getTodayDate());
        if (sendCount >= FrontConst.SMS_CODE_MOBILE_DAY_MAX_SEND_COUNT) {
            return new BaseResponse<>(FrontRetEnum.SMS_CODE_MOBILE_SEND_EXCESS);
        }
        sendCount = smsCodeDao.countByIpAndDate(WebContext.getRequestIp(), DateUtil.getTodayDate());
        if (sendCount >= FrontConst.SMS_CODE_IP_DAY_MAX_SEND_COUNT) {
            return new BaseResponse<>(FrontRetEnum.SMS_CODE_IP_SEND_EXCESS);
        }

        // 非生产环境，测试专用验证码
        if (!businessProps.isProEnv()) {
            code = "666666";
        }

        // 校验验证码是否短期内重复发送
        Long lastSendTime = NumberUtils.toLong(redisCache.getString(cacheKey + mobile + FrontConst.CACHE_KEY_SMS_CODE_C_T), -1L);
        if (null != lastSendTime || lastSendTime <= 0) {
            long usedTime = (System.currentTimeMillis() - lastSendTime) / 1000;
            long remainTime = FrontConst.SMS_CODE_SEND_REPEAT_INTERVAL - usedTime;
            if (remainTime > 0) {
                return BaseResponse.fail("请" + remainTime + "秒之后再点击发送");
            }
        }

        // 存入缓存
        redisCache.set(cacheKey + mobile, code, FrontConst.SMS_CODE_SEND_VALID_TIME);

        // 生产环境，请求第三方发送验证码
        if (businessProps.isProEnv()) {
            if (!sms.sendCode(mobile, code)) {    // 返回失败
                return new BaseResponse<>(FrontRetEnum.SMS_CODE_SEND_EXCEPTION);
            }
        }

        // 添加时间间隔限制
        redisCache.set(cacheKey + mobile + FrontConst.CACHE_KEY_SMS_CODE_C_T, String.valueOf(System.currentTimeMillis()),
                FrontConst.SMS_CODE_SEND_REPEAT_INTERVAL);

        // 添加用户发送记录
        SmsCode smsCode = new SmsCode();
        smsCode.setMobile(mobile);
        smsCode.setIp(WebContext.getRequestIp());
        smsCode.setCode(code);
        smsCodeDao.save(smsCode);

        return new BaseResponse();
    }

    public boolean checkCode(String cacheKey, String mobile, String code) {
        return checkCode(cacheKey, mobile, code, false);
    }

    public boolean checkCode(String cacheKey, String mobile, String code, boolean isDelCache) {
        try {
            // 读取缓存
            String cacheCode = redisCache.getString(cacheKey + mobile);

            // 校验验证码
            if (StringUtils.isNotBlank(cacheCode) && cacheCode.equals(code)) {    // 验证码匹配
                if (isDelCache) {
                    // 删除缓存中的验证码
                    redisCache.del(cacheKey + mobile);
                }
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            log.error("校验短信验证码异常！", e);
            return false;
        }
    }
}
